﻿using System.Data.EntityClient;
using System.Globalization;
using System.Text.RegularExpressions;
using DotNetNuke.Common.Utilities;

namespace BrandonHaynes.ModelAdapter.EntityFramework
	{
	/// <summary>
	/// Adapts an Entity Framework model to utilize a DotNetNuke installation's ObjectQualifier and DatabaseOwner,
	/// when development and deployment environments vary.
	/// </summary>
	public class DotNetNukeObjectContext : AdaptingObjectContext
		{
		/// <summary>
		/// Instantiates a DotNetNuke-adapted ObjectContext
		/// </summary>
		/// <param name="connectionString">The unadapted Entity Framework connection string</param>
		/// <param name="defaultContainerName">The default Entity Framework container name</param>
		public DotNetNukeObjectContext(string connectionString, string defaultContainerName)
			: base(AdaptConnectionString(connectionString), defaultContainerName, new ConnectionAdapter(new DotNetNukeModelAdapter(), System.Reflection.Assembly.GetCallingAssembly()))
			{ }

		/// <summary>
		/// Instantiates a DotNetNuke-adapted ObjectContext
		/// </summary>
		/// <param name="connection">The Entity Framework connection to use (Note: this value is used directly, bypassing DotNetNuke connection adaptation)</param>
		/// <param name="defaultContainerName">The default Entity Framework container name</param>
		public DotNetNukeObjectContext(EntityConnection connection, string defaultContainerName)
			: base(connection, defaultContainerName, new ConnectionAdapter(new DotNetNukeModelAdapter(), System.Reflection.Assembly.GetCallingAssembly()))
			{ }

		/// <summary>
		/// Adapts an Entity Framework connection string (of the format 
		/// "metadata=res://*/DotNetNuke.csdl|res://*/DotNetNuke.ssdl|res://*/DotNetNuke.msl;provider=System.Data.SqlClient;provider connection string=&quot;{{ adapted connection string }}&quot;")
		/// to utilize the current DotNetNuke installation's connection string.
		/// </summary>
		/// <param name="originalConnectionString">The original Entity Framework connection string</param>
		/// <returns>A connection string adapted to target the DotNetNuke data store</returns>
		private static string AdaptConnectionString(string originalConnectionString)
			{
			// "metadata=res://*/DotNetNuke.csdl|res://*/DotNetNuke.ssdl|res://*/DotNetNuke.msl;provider=System.Data.SqlClient;provider connection string=&quot;Data Source=(local);Initial Catalog=DotNetNuke;Integrated Security=True;MultipleActiveResultSets=True&quot;"
			const string originalConnectionStringPattern = @"provider connection string="".*""";
			const string adaptedConnectionStringFormat = @"provider connection string=""{0}""";

			// When the connection string points to a string persisted in the Config, load and adapt that value
			if (originalConnectionString.StartsWith("name=", System.StringComparison.OrdinalIgnoreCase))
				return AdaptConnectionString(Config.GetConnectionString(Regex.Replace(originalConnectionString, "name=", string.Empty, RegexOptions.IgnoreCase)));
			// Otherwise replace the provider connection string with the DotNetNuke value
			else
				return Regex.Replace(originalConnectionString, originalConnectionStringPattern, string.Format(CultureInfo.InvariantCulture, adaptedConnectionStringFormat, Config.GetConnectionString()));
			}
		}
	}
